package com.stlm2.controller.shiro;

import com.google.gson.Gson;
import com.stlm2.core.base.BaseController;
import com.stlm2.core.common.md5.MD5;
import com.stlm2.core.redis.RedisClient;
import com.stlm2.dems.entity.User;
import com.stlm2.dems.user.dao.RoleDao;
import com.stlm2.dems.dao.UserDao;
import com.stlm2.dems.user.dao.UserRoleDao;
import com.stlm2.dems.user.entity.*;
import com.stlm2.util.Memcached;
import com.stlm2.util.codecontent.CodeContent;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.Set;

/**
 * Created by ZLQ on 2017/7/12.
 */
@Controller
@RequestMapping("/shiroLongC")
public class ShiroLoginController  extends BaseController {
    @Resource
    private Memcached memcached;
    @Resource
    private UserDao userDao;
    @Resource
    private UserRoleDao userRoleDao;
    @Resource
    private RoleDao roleDao;

    /**
     * 获得登录密码的Md5key
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value="/userLoginKey.json",produces="application/json;charset=UTF-8")
    public String userLoginKey(HttpServletRequest request, ModelMap model, String userName) throws Exception{

        if(org.apache.commons.lang.StringUtils.isBlank(userName)){
            return  CodeContent.getModelByCode(0,"请输入用户名",model);
        }
        User user = userDao.getByName(userName);
        if(user == null || UserState.Invalid.equals(user.getUserState())) {
            return  CodeContent.getModelByCode(0,"用户不存在",model);
        }
        if(user.getUserType().equals(UserType.Normal)  ){
            return  CodeContent.getModelByCode(0,"无权登录",model);
        }
        if(user.getUserState().equals(UserState.Invalid)){
            return  CodeContent.getModelByCode(0,"用户状态无效",model);
        }

        String md5key = "";
        if (user != null && !UserState.Invalid.equals(user.getUserState()))
            md5key = user.getUserKey();
        model.put("result","success");
        model.put("userKey", md5key);

        return CodeContent.getModelByCode(1,"",model);
    }
    /**
     * 登录
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping(value="/crmLogin.json",produces="application/json;charset=UTF-8")
    public String crmLogin(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
        String userName = request.getParameter("userName");
        String password = request.getParameter("passWord");
        StringBuffer url = request.getRequestURL();
        String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append("/").toString();
        System.out.println(tempContextUrl);
        Boolean rememberMe = Boolean.getBoolean(request.getParameter("rememberMe"));
        if(org.apache.commons.lang.StringUtils.isBlank(userName) || org.apache.commons.lang.StringUtils.isBlank(password)){
            return  CodeContent.getModelByCode(0,"请输入用户名和密码",model);
        }
        int loginFailureNum=getLoginFailureNum(userName,tempContextUrl);
        if(loginFailureNum>4){
            return  CodeContent.getModelByCode(0,"密码错误次数已达5次，请3个小时后重试",model);
        }
        //通过Shiro登录认证前提前获取用户数据，并判断是否允许登录
        User user=userDao.getByName(userName);

        if(user!=null){
            if(user.getUserType().equals(UserType.Normal) ){
                return  CodeContent.getModelByCode(0,"无权登录",model);
            }
            if(user.getUserState().equals(UserState.Invalid)){
                return  CodeContent.getModelByCode(0,"用户状态无效",model);
            }
        }else {
            return  CodeContent.getModelByCode(0,"用户不存在",model);
        }
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, password,tempContextUrl);

        usernamePasswordToken.setRememberMe(true);
        try {
            //通过Shiro进行登录认证并授权
          //  SecurityUtils.getSubject().login(usernamePasswordToken);
            Subject currentUser = SecurityUtils.getSubject();
            currentUser.login(usernamePasswordToken);

        }catch (UnknownAccountException e) {
            return CodeContent.getModelByCode(0,"用户名不正确",null);
        }catch (IncorrectCredentialsException e){
            loginFailureNum(userName,tempContextUrl);
            int num=getLoginFailureNum(userName,tempContextUrl);
            return CodeContent.getModelByCode(0,"密码错误，错误次数达5次，账户将锁定3个小时，当前第" + num + "次",null);
        }

        boolean isAuthenticated = SecurityUtils.getSubject().isAuthenticated();
        if(isAuthenticated){
            String	token = MD5.encryptMD5(user.getId() + user.getPassword() + new Date().toString());
            model.put("token", token);
            Gson gson = new Gson();
            model.put("realName",user.getRealName());
            UserRole userRole=userRoleDao.getByUserId(user.getId());
            model.put("role",AllRole.getByIntValue(userRole.getRoleId()).toString());
            model.put("roleValue",AllRole.getByIntValue(userRole.getRoleId()).getIntValue());

            model.put("userTypeValue",user.getUserTypeValue());
            model.put("userType",user.getUserType()!=null?user.getUserType().toString():"");
            memcached.set(token, 36000, gson.toJson(user).toString()); //将对象和其token值存放在缓存中
        }
        return CodeContent.getModelByCode(1,"sucess", model);
    }

    /*zlq
* 退出
* */
    @ResponseBody
    @RequestMapping(value="/exit.json",produces="application/json;charset=UTF-8")
    public String exit(HttpServletRequest request,ModelMap map,String token){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            StringBuffer url = request.getRequestURL();
            String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append("/").toString();
            pool = RedisClient.getPool();
            jedis = pool.getResource();
        User loginUser = userDao.getByToken(token);
        if (loginUser!= null) {
            Set<String> userPrivilegeList=jedis.keys(tempContextUrl + loginUser.getName() + "userPrivilege*");
            if(userPrivilegeList!=null&&userPrivilegeList.size()>0){
                for (String userPrivilege:userPrivilegeList) {//删除之前存入用户缓存的权限
                    jedis.del(userPrivilege);
                }
            }
            Set<String> userRolesList=jedis.keys(tempContextUrl +  loginUser.getName() + "userRoles*");
            if(userRolesList!=null&&userRolesList.size()>0){
                for (String userRoles:userRolesList) {//删除之前存入用户角色
                    jedis.del(userRoles);
                }
            }
        }
            memcached.delete(token);

        }catch (Exception e){
            e.printStackTrace();
            //如果产生异常，该异常不处理，直接返回“sucess”，前台会跳转/logout路径，执行Shiro的退出登录方法，跳转登录页面
            return CodeContent.getModelByCode(1,"sucess", map);
        }
        finally {
            pool.returnResource(jedis);
        }
        return CodeContent.getModelByCode(1,"sucess", map);
    }

/*
*zlq
* 记录密码错误数量
 */
    private void loginFailureNum(String userName,String tempContextUrl){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = RedisClient.getPool();
            jedis = pool.getResource();
            StringBuffer key2=new StringBuffer();
            key2.append(tempContextUrl);
            key2.append("loginFailureNum:");
            key2.append(userName);
            if(jedis.exists(key2.toString())){
                jedis.incr(key2.toString());
            }else {
                jedis.set(key2.toString(),"1");
                jedis.expire(key2.toString(),60*30);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            pool.returnResource(jedis);
        }
    }
    /*
    *zlq
    * 获取密码失败次数
     */
    private int getLoginFailureNum(String userName,String tempContextUrl){
        JedisPool pool = null;
        Jedis jedis = null;
        int num =0;
        try {
            pool = RedisClient.getPool();
            jedis = pool.getResource();
            StringBuffer key2=new StringBuffer();
            key2.append(tempContextUrl);
            key2.append("loginFailureNum:");
            key2.append(userName);
            if(jedis.exists(key2.toString())){
                String v=jedis.get(key2.toString());
                num=Integer.parseInt(v);
            }
        }catch (Exception e){
            e.printStackTrace();
            return num;
        }
        finally {
            pool.returnResource(jedis);
        }
        return num;
    }
}
